package cn.wsalix.admin.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import cn.anlaser.service.impl.ParentServiceImpl;
import cn.anlaser.utils.SearchFilter;
import cn.anlaser.utils.SearchFilter.Operator;
import cn.wsalix.admin.entity.SysMenu;
import cn.wsalix.admin.entity.SysRole;
import cn.wsalix.admin.form.MenuForm;
import cn.wsalix.admin.repository.MenuRepository;
import cn.wsalix.admin.repository.PermitRepository;
import cn.wsalix.admin.service.MenuService;
import cn.wsalix.admin.service.RoleService;
import cn.wsalix.admin.status.MenuEnum;

@Service("menuService")
public class MenuServiceImpl extends
		ParentServiceImpl<MenuForm, MenuRepository, SysMenu> implements
		MenuService {
	@Autowired
	private MenuRepository menuRepository;
	@Autowired
	private RoleService roleService;
	@Autowired
	private PermitRepository PermitRepository;

	@Override
	public MenuRepository getRepository() {
		return menuRepository;
	}

	@Override
	public String module() {
		return "/admin/menu";
	}

	@Override
	public Class<SysMenu> getEntityClazz() {
		return SysMenu.class;
	}

	@Override
	public Map<String, SearchFilter> buildByForm(MenuForm form) {
		Map<String, SearchFilter> filters = buildFilter();
		if (form.getCode() != null) {
			filters.put("code",
					new SearchFilter("code", Operator.EQ, form.getCode()));
		}
		if (form.getName() != null) {
			filters.put("name",
					new SearchFilter("name", Operator.EQ, form.getName()));
		}
		if (form.getMenuUrl() != null) {
			filters.put("menuUrl", new SearchFilter("menuUrl", Operator.EQ,
					form.getMenuUrl()));
		}
		if (form.getStatus() != null) {
			filters.put("status", new SearchFilter("status", Operator.EQ, form
					.getStatus().ordinal()));
		}
		if (form.isParentNull()) {
			filters.put("parent", new SearchFilter("parent.id",
					Operator.ISNULL, null));
		}
		if (form.getParentId() != null && form.getParentId() != 0) {
			filters.put("parent.id", new SearchFilter("parent.id", Operator.EQ,
					form.getParentId()));
		}

		return filters;
	}

	// @Cacheable(value = "menuCache",key="#id")
	@Override
	public SysMenu findById(Long id) {
		return super.findById(id);
	}

	// @CacheEvict(value = "myMenuCache", allEntries = true)
	@CacheEvict(value = "menuCache", key = "#form.getId()")
	@Override
	public SysMenu edit(MenuForm form) {
		upUserRoleByMenuId(form.getId());
		return super.edit(form);
	}

	private void upUserRoleByMenuId(Long menuId) {
		List<SysRole> roles = roleService.findRolesByMenuId(menuId);
		for (SysRole role : roles) {
			roleService.upUserRole(role.getId());
		}
	}

	@CacheEvict(value = "menuCache", allEntries = true)
	public void reload() {
	}

	@CacheEvict(value = "menuCache", key = "#id")
	// @CacheEvict(value = "myMenuCache", allEntries = true)
	@Override
	public void delete(Long id) {
		upUserRoleByMenuId(id);
		super.delete(id);
	}

	@Override
	public void delete(Iterable<SysMenu> entitys) {
		// TODO Auto-generated method stub
		super.delete(entitys);
	}

	@Override
	public List<SysMenu> findUnMenusByRoleId(Long roleId) {
		// TODO Auto-generated method stub
		return menuRepository.findUnMenusByRoleId(roleId);
	}

	@Cacheable(value = "myMenuCache", key = "#userId")
	@Override
	public List<SysMenu> findMenusByUserId(Long userId) {
		/*
		 * List<SysMenu>
		 * resParentMenus=menuRepository.findParentNullByUserId(userId);
		 * List<SysMenu> resMenu=new ArrayList<SysMenu>(); for(SysMenu
		 * menuItem:resParentMenus){ List<SysMenu>
		 * resMenus=menuRepository.findByUserIdAndParentId
		 * (menuItem.getId(),userId); menuItem.setChilds(resMenus);
		 * resMenu.add(menuItem); }
		 */
		List<SysMenu> menus = menuRepository.findByUserId(userId);
		List<SysMenu> resMenu = new ArrayList<SysMenu>();
		for (SysMenu menuItem : menus) {
			if (menuItem.getParent() == null) {
				for (SysMenu menuChild : menus) {
					if (menuChild.getParent() != null) {
						if (menuChild.getParent().getId() == menuItem.getId()) {
							if (menuItem.getChilds() == null) {
								menuItem.setChilds(new ArrayList<SysMenu>());
							}
							if (!menuItem.getChilds().contains(menuChild)) {
								menuItem.getChilds().add(menuChild);
							}
						}
					}
				}
				resMenu.add(menuItem);
			}
		}
		
		return resMenu;
	}

	@Override
	public SysMenu findByUrl(String menuUrl) {
		MenuForm form = new MenuForm();
		form.setMenuUrl(menuUrl);
		List<SysMenu> menus = findByForm(form);
		if (menus.size() != 1) {
			if (menus.size() > 1) {
				logger.error(menuUrl + " : size() > 1 [" + menus.size() + "]");
				return menus.get(0);
			}
			logger.error(menuUrl + " : size() =0 ");
			return null;
		} else {
			return menus.get(0);
		}
	}

	@Override
	public List<SysMenu> findUnsByPermitId(Long permitId) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public SysMenu findByCodeOne(String code) {
		logger.info(code);
		List<SysMenu> menus = findsByCode(code);
		if (menus.size() != 1) {
			if (menus.size() > 1) {
				logger.error(code + " : size() > 1 [" + menus.size() + "]");
				return menus.get(0);
			}
			logger.error(code + " : size() =0 ");
			return null;
		} else {
			return menus.get(0);
		}
	}

	@Override
	public SysMenu findByNameOne(String name) {
		logger.info(name);
		List<SysMenu> menus = findsByName(name);
		if (menus.size() != 1) {
			if (menus.size() > 1) {
				logger.error(name + " : size() > 1 [" + menus.size() + "]");
				return menus.get(0);
			}
			logger.error(name + " : size() =0 ");
			return null;
		} else {
			return menus.get(0);
		}
	}

	@Override
	public List<SysMenu> findsByName(String name) {
		return menuRepository.findByName(name);
	}

	@Override
	public List<SysMenu> findsByCode(String code) {
		return menuRepository.findByCode(code);
	}

	@Override
	public List<SysMenu> findSubsById(Long parentId) {
		MenuForm form = new MenuForm();
		form.setParentId(parentId);
		form.setStatus(MenuEnum.invocation);
		return findByForm(form);
	}

}
